package com.jiepos.mpos.pay.quickpay.service.epaypp;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.epayplusplus.api.DefaultEpayppClient;
import com.epayplusplus.api.EpayppApiException;
import com.epayplusplus.api.EpayppClient;
import com.epayplusplus.api.EpayppResponse;
import com.epayplusplus.api.enums.FormatEnum;
import com.epayplusplus.api.enums.SignMethodEnum;
import com.epayplusplus.api.request.EpayppMerchantCardExpressPayOpenRequest;
import com.epayplusplus.api.request.EpayppTradeCreateRequest;
import com.epayplusplus.api.request.EpayppTradeQueryRequest;
import com.epayplusplus.api.request.EpayppWithoutCardTradeExpressVerifyCodeSubmitRequest;
import com.epayplusplus.api.request.EpayppWithoutCardTradePayRequest;
import com.epayplusplus.api.response.EpayppMerchantCardExpressPayOpenResponse;
import com.epayplusplus.api.response.EpayppTradeCreateResponse;
import com.epayplusplus.api.response.EpayppTradeQueryResponse;
import com.epayplusplus.api.response.EpayppWithoutCardTradeExpressVerifyCodeSubmitResponse;
import com.epayplusplus.api.response.EpayppWithoutCardTradePayResponse;
import com.jiepos.mpos.common.constant.SystemConstant;
import com.jiepos.mpos.core.util.DateUtil;
import com.jiepos.mpos.core.util.GlobalUtils;
import com.jiepos.mpos.core.util.MathUtils;
import com.jiepos.mpos.core.util.StringUtils;
import com.jiepos.mpos.pay.CommonService;
import com.jiepos.mpos.pay.quickpay.service.AtrPayService;

/**
 * 
* 标题:
* 模块: 融商支付公共服务类
* 描 述: <描述>
* 版权: Copyright (c) 2017 江苏杰博实信息技术有限公司
* @author 杨剑武
* @version 1.0
* @since 2017年12月16日
* @history（历次修订内容、修订人、修订时间等）
 */
@SuppressWarnings("rawtypes")
public class EpayppCommonService extends AtrPayService  {
	private static final Logger _log = LoggerFactory.getLogger(EpayppCommonService.class);
	protected static final String EPAYPP_RSPMSG_62 = "请使用62开头的标准银联卡";
	protected EpayppClient epayppClient;

	public EpayppCommonService() {
		this.epayppClient = new DefaultEpayppClient(GlobalUtils.getPayConfProperty("epaypp.serverurl"),
				GlobalUtils.getPayConfProperty("epaypp.partnerid"), GlobalUtils.getPayConfProperty("epaypp.pkcs8privatekey"),
				FormatEnum.JSON, SystemConstant.UTF_ENCODING, GlobalUtils.getPayConfProperty("epaypp.pkcs8publickey"),
				SignMethodEnum.RSA);
	}
	
	/**
	 * 
	 * 接口: 商户银行卡快捷支付功能开通请求
	 * 
	 * @param dataMap
	 * @return
	 * @throws Exception
	 * @since 2017年12月4日
	 */
	protected EpayppResponse epayppMerchantCardExpressPayOpen(Map dataMap) throws Exception {
		JSONObject bcJson = new JSONObject();
		bcJson.put("out_user_id", dataMap.get("trf_mchnt_cd"));// 渠道商户号
		bcJson.put("product", GlobalUtils.getPayConfProperty("epaypp.product." + dataMap.get("channel_No")));
		bcJson.put("bank_account_type", GlobalUtils.getPayConfProperty("epaypp.bank.account.type"));
		bcJson.put("bank_account_no", dataMap.get("act_out_no"));
		bcJson.put("name", dataMap.get("real_name"));
		bcJson.put("cert_type", GlobalUtils.getPayConfProperty("epaypp.cert.type"));
		bcJson.put("cert_no", dataMap.get("certificate_no"));
		bcJson.put("mobile", dataMap.get("phone"));
		bcJson.put("cvn2", dataMap.get("cvv2"));
		bcJson.put("expired", dataMap.get("exptm"));
		_log.info("融商支付({})商户银行卡快捷支付功能开通请求参数:[{}]", dataMap.get("channel_No"), bcJson);
		EpayppMerchantCardExpressPayOpenRequest request = new EpayppMerchantCardExpressPayOpenRequest();
		request.setBizContent(bcJson.toJSONString());
		EpayppMerchantCardExpressPayOpenResponse response = epayppClient.execute(request);
		_log.info("融商支付({})商户银行卡快捷支付功能开通请求响应:[success={},resultCode={},resultCodeMsg={},body={},params={}]",
				dataMap.get("channel_No"), response.isSuccess(), response.getResultCode(), response.getResultCodeMsg(),
				response.getBody(), response.getParams());
		return response;
	}

	/**
	 * 接口:交易创建
	 * 
	 * @param dataMap
	 * @return
	 * @throws Exception
	 * @since 2017年12月4日
	 */
	protected EpayppResponse epayppTradeCreate(Map dataMap) throws Exception {
		EpayppTradeCreateRequest request = new EpayppTradeCreateRequest();
		// 是否需要对业务参数进行加密
		request.setNeedEncrypt(true);
		// 异步通知地址
		request.setNotifyUrl(dataMap.get("payUrl") + GlobalUtils.getPayConfProperty("epaypp.notice.fyurl"));
		// 同步跳转地址，对于网页收银台需要此参数
		request.setReturnUrl(dataMap.get("payUrl") + GlobalUtils.getPayConfProperty("epaypp.notice.returnurl"));
		// SDK已经封装掉了公共参数，这里只需要传入业务参数
		JSONObject bcJson = new JSONObject();
		// 交易产品，固定值：TRADE_GATHERING
		bcJson.put("product", GlobalUtils.getPayConfProperty("epaypp.product." + dataMap.get("channel_No")));
		// 卖家用户号，子商户号
		bcJson.put("out_user_id", dataMap.get("trf_mchnt_cd"));// 渠道商户号
		// 终端编号，固定值
		bcJson.put("terminal_id", dataMap.get("trf_term_id"));// 渠道终端号
		// 订单支付超时时间，单位：秒（默认为600s）
		bcJson.put("timeout", SystemConstant.EPAYPP_TIME_OUT);
		if (!StringUtils.isEmpty(GlobalUtils.getPayConfProperty("epaypp.timeout"))) {
			bcJson.put("timeout", GlobalUtils.getPayConfProperty("epaypp.timeout"));
		}
		// 资金条款
		bcJson.put("currency", GlobalUtils.getPayConfProperty("epaypp.currency"));
		bcJson.put("total_fee", dataMap.get("trans_at"));
		// 商品条款
		// 摘要，收银界面显示
		bcJson.put("summary", "无卡支付");
		// 合作伙伴条款
		// 商户订单号
		bcJson.put("out_trade_no", dataMap.get("loc_trace_no"));
		// 商户订单创建时间格式：yyyy-MM-dd HH:mm:ss
		bcJson.put("gmt_out_create", DateUtil.toString(new Date()));
		_log.info("融商支付({})交易创建请求参数:[{},异步通知地址={},同步跳转地址={}]", dataMap.get("channel_No"), bcJson,
				request.getNotifyUrl(), request.getReturnUrl());
		// 将所有的业务参数放入bizContent参数中
		request.setBizContent(bcJson.toJSONString());
		// 构建易支付客户端实例，执行调用请求
		EpayppTradeCreateResponse response = this.epayppClient.execute(request);
		_log.info("融商支付({})交易创建请求响应数据:[success={},resultCode={},resultCodeMsg={},body={},params={}]",
				dataMap.get("channel_No"), response.isSuccess(), response.getResultCode(), response.getResultCodeMsg(),
				response.getBody(), response.getParams());
		return response;
	}

	/**
	 * 
	 * 接口: 交易支付请求
	 * 
	 * @param dataMap
	 * @return
	 * @throws Exception
	 * @since 2017年12月4日
	 */
	protected EpayppResponse epayppWithoutCardTradePay(Map dataMap) throws Exception {
		JSONObject bcJson = new JSONObject();
		bcJson.put("out_trade_no", dataMap.get("loc_trace_no"));
		bcJson.put("other_params",
				String.format(GlobalUtils.getPayConfProperty("epaypp.params"), dataMap.get("real_name"),
						dataMap.get("certificate_no"), dataMap.get("act_out_no"), dataMap.get("phone")));
		_log.info("融商支付({})交易支付请求参数:[{}]", dataMap.get("channel_No"), bcJson);
		EpayppWithoutCardTradePayRequest request = new EpayppWithoutCardTradePayRequest();
		request.setBizContent(bcJson.toJSONString());
		EpayppWithoutCardTradePayResponse response = this.epayppClient.execute(request);
		_log.info("融商支付({})交易支付请求响应数据:[success={},resultCode={},resultCodeMsg={},body={},params={}]",
				dataMap.get("channel_No"), response.isSuccess(), response.getResultCode(), response.getResultCodeMsg(),
				response.getBody(), response.getParams());
		return response;
	}
	
	/**
	 * 
	 * 接口: 融商支付手机验证码
	 * 
	 * @param dataMap
	 * @return
	 * @throws EpayppApiException
	 * @since 2017年12月5日
	 */
	protected EpayppResponse epayppWithoutCardTradeExpressVerifyCodeSubmit(Map dataMap) throws Exception {
		JSONObject bcJson = new JSONObject();
		bcJson.put("out_trade_no", dataMap.get("loc_trace_no"));
		bcJson.put("mobile", dataMap.get("phone"));
		bcJson.put("verify_code", dataMap.get("verify_code"));
		_log.info("融商支付({})验证码提交请求参数:[{}]", dataMap.get("channel_No"), bcJson);
		EpayppWithoutCardTradeExpressVerifyCodeSubmitRequest request = new EpayppWithoutCardTradeExpressVerifyCodeSubmitRequest();
		request.setBizContent(bcJson.toJSONString());
		EpayppWithoutCardTradeExpressVerifyCodeSubmitResponse response = epayppClient.execute(request);
		_log.info("融商支付({})验证码提交请求响应:[success={},resultCode={},resultCodeMsg={},body={},params={}]",
				dataMap.get("channel_No"), response.isSuccess(), response.getResultCode(), response.getResultCodeMsg(),
				response.getBody(), response.getParams());
		return response;
	}

	/**
	 * @param reqMap
	 * @return
	 * @throws Exception
	 */

	@Override
	public Map<String, String> getStandardData(Map<String, String> reqMap) throws Exception {
		return null;
	}

	/**
	 * 
	 * 接口: 获取渠道返回respcode和respmsg
	 * 
	 * @return
	 * @since 2017年12月13日
	 */
	protected Map<String, String> getRespCode(Map<String, String> reqMap, EpayppResponse response) {
		reqMap.put("rspcode", response.getResultCode());
		reqMap.put("rspmsg", response.getResultCodeMsg());
		Map<String, String> respMap = new HashMap<String, String>();
		respMap = CommonService.parseJsonToMap(response.getBody(), respMap);
		if (!StringUtils.isEmpty(respMap.get("sub_code")) && !StringUtils.isEmpty(respMap.get("sub_msg"))) {
			reqMap.put("rspcode", respMap.get("sub_code"));
			reqMap.put("rspmsg", respMap.get("sub_msg"));
		}
		return respMap;
	}

	/**
	 * 
	 * 接口: 交易必须为62开头的标准银联卡
	 * 
	 * @param act_out_no
	 * @return
	 * @since 2017年12月15日
	 */

	protected boolean verificationCardNo(String act_out_no) {
		if (SystemConstant.EPAYPP_CARD_TYPE.equals(act_out_no.substring(0, 2))) {
			return true;
		}
		return false;
	}
	
	/**
	 * 融商异步通知标准化报文
	 * @param payResMap
	 * @return
	 */
	protected Map<String, String> noticeStandard(Map<String, String> payResMap) {
		Map<String, String> infoMap = appLogTransJnlsPayService.getTranInfo(payResMap.get("out_trade_no"));
		Map<String, String> standardDataMap = new HashMap<String, String>();
		standardDataMap.put("trf_mchnt_cd", "");// 商户编号（渠道）
		standardDataMap.put("trf_term_id", "");// 终端编号（渠道）		
		String gmt_pay_dt=StringUtils.isBlank(String.valueOf(payResMap.get("gmt_pay")))?"":DateUtil.toString(DateUtil.StrToDate(String.valueOf(payResMap.get("gmt_pay"))),"yyyyMMdd");
		String gmt_pay_ts=StringUtils.isBlank(String.valueOf(payResMap.get("gmt_pay")))?"":DateUtil.toString(DateUtil.StrToDate(String.valueOf(payResMap.get("gmt_pay"))),"HHmmss");
		standardDataMap.put("complete_dt", gmt_pay_dt);// 订单完成日期（渠道）
		standardDataMap.put("complete_ts", gmt_pay_ts);// 订单完成时间（渠道）
		standardDataMap.put("custom_no", "");// 商户编号（支付系统）
		standardDataMap.put("term_id", "");// 终端编号（支付系统）
		standardDataMap.put("trf_trace_no", payResMap.get("trade_no"));// 渠道方流水号（渠道）
		standardDataMap.put("loc_trace_no", payResMap.get("out_trade_no"));// 本地流水号（支付系统）

		standardDataMap.put("trs_stat",
				CommonService.encapRespCode(payResMap.get("trade_status"), null));// 交易状态
		String stlst = CommonService.encapSettleRespCode(payResMap.get("trade_status"));
		standardDataMap.put("stlst", stlst);// 清算状态（出款状态）
		standardDataMap.put("stl_dt", gmt_pay_dt);// 清算日期			
		standardDataMap.put("midfee", "");// 商户手续费		
		standardDataMap.put("costfee", StringUtils.isBlank(String.valueOf(payResMap.get("charge_amount")))?"":String.valueOf(MathUtils.mul(Double.parseDouble(String.valueOf(payResMap.get("charge_amount"))), Double.parseDouble("100"))));// 成本手续费	
		standardDataMap.put("stl_amt", String.valueOf(MathUtils.mul(MathUtils.sub(Double.parseDouble(String.valueOf(payResMap.get("amount"))), Double.parseDouble(String.valueOf(infoMap.get("midfee")))), Double.parseDouble("100"))));// 结算金额
		standardDataMap.put("trans_at", String.valueOf(MathUtils.mul(Double.parseDouble(String.valueOf(payResMap.get("amount"))), Double.parseDouble("100"))));// 交易金额
		String rspcode = CommonService.encapRespCode(payResMap.get("trade_status"), null);
		String rspmsg = SystemConstant.RSPCODE_SUCCESS.equals(rspcode) ? SystemConstant.RSPCODE_SUCCESS_PAY
				: String.valueOf(noticeService.getRspCodeListMap().get(rspcode));
		standardDataMap.put("rspcode", rspcode);// 返回码
		standardDataMap.put("rspmsg", rspmsg);// 返回信息描述
		standardDataMap.put("pay_dt", gmt_pay_dt);// 出款日期
		standardDataMap.put("pay_ts", gmt_pay_ts);// 出款时间
		_log.info("融商标准化异步通知报文map=[{}]", standardDataMap);
		return standardDataMap;
	}
	
	/**
	 * 融商主动查询
	 * @param dataMap
	 * @return
	 * @throws EpayppApiException
	 */
	protected Map<String, Object> epayppTradeQuery(Map dataMap) throws EpayppApiException{
		Map<String, Object> repMap=new HashMap<String, Object>();
		// SDK已经封装掉了公共参数，这里只需要传入业务参数
        JSONObject bcJson = new JSONObject();
        bcJson.put("out_trade_no", dataMap.get("loc_trace_no"));
                  
        _log.info("融商主动查询请求参数:[{}]", bcJson);
        EpayppTradeQueryRequest request = new EpayppTradeQueryRequest();
        request.setBizContent(bcJson.toJSONString());
        EpayppTradeQueryResponse response = this.epayppClient.execute(request);
        _log.info("融商主动查询请求响应:[success={},resultCode={},resultCodeMsg={},body={},params={}]",
				response.isSuccess(), response.getResultCode(), response.getResultCodeMsg(), response.getBody(),
				response.getParams());
        
        //调用成功，则处理业务逻辑
        if (response.isSuccess()) {
        	//转换返回报文       	            
            repMap=JSON.parseObject(response.getBody());                       
        }
		return repMap;
	}
	
	/**
	 * 融商主动查询标准化报文
	 * @param payResMap
	 * @param loc_trace_no
	 * @return
	 */
	protected Map<String, String> queryStandard(Map<String, Object> payResMap,String loc_trace_no){
		Map<String, String> respMap = new HashMap<String, String>();
		Map<String, String> infoMap = appLogTransJnlsPayService.getTranInfo(loc_trace_no);
		respMap.put("trf_mchnt_cd", infoMap.get("trf_mchnt_cd"));// 商户编号（渠道）
		respMap.put("trf_term_id", infoMap.get("trf_term_id"));// 终端编号（渠道）
		respMap.put("custom_no", infoMap.get("custom_no"));// 客户编号（支付系统）
		respMap.put("loc_trace_no", loc_trace_no);// 本地流水号（支付系统)
		respMap.put("stlst", infoMap.get("stlst"));// 清算状态(待定)
		respMap.put("trans_at", String.valueOf(MathUtils.mul(Double.valueOf(infoMap.get("trans_at")), 100)));// 交易金额(数据库查询)
		respMap.put("midfee", String.valueOf(MathUtils.mul(Double.valueOf(infoMap.get("midfee")), 100)));// 商户手续费
		String rspcode = infoMap.get("rspcode");// 返回码
		String rspmsg = infoMap.get("rspmsg");// 交易返回信息
		if (payResMap!=null&&!payResMap.isEmpty()) {
			rspcode=CommonService.encapResultCode(String.valueOf(payResMap.get("result_code")));
			
			if(SystemConstant.RSPCODE_SUCCESS.equals(rspcode)){				
				Map order=JSON.parseObject(String.valueOf(payResMap.get("order")));
				Map charge_fee=JSON.parseObject(String.valueOf(order.get("charge_fee")));
				Map total_fee=JSON.parseObject(String.valueOf(order.get("total_fee")));
				String gmt_pay_dt=StringUtils.isBlank(String.valueOf(payResMap.get("gmt_pay")))?"":DateUtil.toString(DateUtil.StrToDate(String.valueOf(payResMap.get("gmt_pay"))),"yyyyMMdd");
				String gmt_pay_ts=StringUtils.isBlank(String.valueOf(payResMap.get("gmt_pay")))?"":DateUtil.toString(DateUtil.StrToDate(String.valueOf(payResMap.get("gmt_pay"))),"HHmmss");
				respMap.put("complete_dt", gmt_pay_dt);// 订单完成日期（渠道）
				respMap.put("complete_ts", gmt_pay_ts);// 订单完成时间（渠道）
				respMap.put("term_id", "");// 终端编号（支付系统）
				respMap.put("trf_trace_no", String.valueOf(order.get("trade_no")));// 渠道方流水号（渠道）
				respMap.put("trs_stat", CommonService.encapRespCode(String.valueOf(order.get("status")), null));// 交易状态
				respMap.put("stl_dt", gmt_pay_dt);// 清算日期				
				respMap.put("stl_amt", String.valueOf(MathUtils.mul(MathUtils.sub(Double.parseDouble(String.valueOf(total_fee.get("amount"))), Double.parseDouble(String.valueOf(infoMap.get("midfee")))), Double.parseDouble("100"))));// 结算金额
				respMap.put("stlst", CommonService.encapSettleRespCode(String.valueOf(order.get("status"))));// 清算状态				
				respMap.put("midfee", "");// 商户手续费
				respMap.put("costfee", String.valueOf(charge_fee.get("cent")));// 成本手续费
				respMap.put("pay_dt", gmt_pay_dt);// 出款日期
				respMap.put("pay_ts", gmt_pay_ts);// 出款时间
				rspcode = CommonService.encapRespCode(String.valueOf(order.get("status")), null);
				rspmsg = SystemConstant.RSPCODE_SUCCESS.equals(rspcode) ? SystemConstant.RSPCODE_SUCCESS_PAY
						: String.valueOf(noticeService.getRspCodeListMap().get(rspcode));	
			}else{
				respMap.put("errorCode", String.valueOf(payResMap.get("result_code")));// 渠道返回码
				respMap.put("msg", String.valueOf(payResMap.get("result_code_msg")));// 渠道返回信息
				rspcode=CommonService.encapRespCode(rspcode,null);
				rspmsg = StringUtils.isBlank( String.valueOf(payResMap.get("result_code_msg"))) ? 
						String.valueOf(noticeService.getRspCodeListMap().get(rspcode)): String.valueOf(payResMap.get("result_code_msg"));
			}
		}			
		respMap.put("rspcode", rspcode);// 返回码
		respMap.put("rspmsg", rspmsg);// 交易返回信息
		_log.info("融商主动查询标准报文map=[{}]", respMap);
		return respMap;
	}	
}
